package uploads_api

import (
	"fmt"
	"gin_study_blog/common"
	"gin_study_blog/common/blog_type"
	"gin_study_blog/common/http"
	"gin_study_blog/models"
	"gin_study_blog/plugins/ali"
	"gin_study_blog/utils"
	"github.com/gin-gonic/gin"
	"io"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

var (
	// LimitationSuffix 图片后缀列表
	LimitationSuffix = []string{
		"jpg",
		"png",
		"jpeg",
		"ico",
		"tiff",
		"gif",
		"svg",
		"webp",
	}
)

type FileUploadResponse struct {
	FileName string `json:"file_name"` // 文件名
	IsOk     bool   `json:"is_ok"`     // 是否上传成功
	Msg      string `json:"msg"`       // 消息
}

// ImageUpload 图片上传
func (UploadsApi) ImageUpload(c *gin.Context) {
	form, err := c.MultipartForm()
	if err != nil {
		http.FailWithMessage("请设置请求头为 multipart/form-data", c)
		return
	}
	fileList, ok := form.File["files"]
	if !ok {
		http.FailWithMessage("请上传文件", c)
		return
	}

	// 判断路径是否存在. 不存在就创建
	basePath := common.Config.Uploads.Path
	_, err = os.ReadDir(basePath)
	if err != nil {
		// 递归常见
		err = os.MkdirAll(basePath, os.ModePerm)
		if err != nil {
			common.Log.Error(err)
		}
	}

	var resList []FileUploadResponse

	// 遍历文件列表并保存到本地
	for _, file := range fileList {
		extName := file.Filename
		// 字符串截取 .后面的内容
		splitName := strings.Split(extName, ".")
		suffix := strings.ToLower(splitName[len(splitName)-1])
		if !utils.Suffix(suffix, LimitationSuffix) {
			resList = append(resList, FileUploadResponse{
				FileName: file.Filename,
				IsOk:     false,
				Msg:      "文件不合法",
			})
			continue
		}
		// 生成随机文件名
		filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), filepath.Ext(file.Filename))
		// 地址拼接
		fileUrl := path.Join(basePath, filename)
		// 判断文件大小
		// 文件上传大小默认为 字节, 我们需要转为 MB
		fileSize := float64(file.Size) / float64(1024*1024)
		if fileSize >= float64(common.Config.Uploads.Size) {
			resList = append(resList, FileUploadResponse{
				FileName: file.Filename,
				IsOk:     false,
				Msg:      fmt.Sprintf("图片大小超过设定大小,当前大小为%.2fMB ,设定大小为: %dMB", fileSize, common.Config.Uploads.Size),
			})
			continue
		}

		fileObj, err := file.Open()
		if err != nil {
			common.Log.Error(err.Error())
		}
		fmt.Printf("fileObj %v type %T", fileObj, fileObj)
		byteData, err := io.ReadAll(fileObj)
		imageHash := utils.Md5(byteData)

		// 判断文件是否已经上传
		var bannerModels models.BannerModel
		err = common.DB.Take(&bannerModels, "image_key = ?", imageHash).Error

		// 如果图片存在就提示图片已经上传
		if err == nil {
			resList = append(resList, FileUploadResponse{
				FileName: bannerModels.Path,
				IsOk:     false,
				Msg:      "图片已存在",
			})
			continue
		}

		if common.Config.QiNiu.Enable {
			filePath, fileUrl, err := ali.UploadImageOss(byteData, filename, "blog")
			if err != nil {
				common.Log.Error(err.Error())
				resList = append(resList, FileUploadResponse{
					FileName: file.Filename,
					IsOk:     false,
					Msg:      err.Error(),
				})
				continue
			}
			resList = append(resList, FileUploadResponse{
				FileName: filePath,
				IsOk:     true,
				Msg:      "上传成功",
			})
			// 图片入库
			common.DB.Create(&models.BannerModel{
				Path:       fileUrl,
				Key:        imageHash,
				Name:       extName,
				ImagesType: blog_type.QinNiu,
			})
			continue
		} else {
			// 保存文件到本地
			err = c.SaveUploadedFile(file, fileUrl)
			if err != nil {
				resList = append(resList, FileUploadResponse{
					FileName: file.Filename,
					IsOk:     false,
					Msg:      err.Error(),
				})
				common.Log.Error(err)
				http.FailWithMessage("文件保存失败，请重新上传", c)
				continue
			}
			resList = append(resList, FileUploadResponse{
				FileName: fileUrl,
				IsOk:     true,
				Msg:      "上传成功",
			})
			// 图片入库
			common.DB.Create(&models.BannerModel{
				Path:       fileUrl,
				Key:        imageHash,
				Name:       extName,
				ImagesType: blog_type.Local,
			})
			continue
		}
	}
	http.IsOkWithData(resList, c)
}
